#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <pthread.h>
#include "list.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h> 
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if_arp.h> 
#include <net/if.h>
#include "common.h"

#define QueueLength 	0x2f
#define CONTROL_INDEX	0x00
#define CONTROL_LENGTH  0x0a
#define CONFIG_INDEX	0x0b
#define CONFIG_LENGTH	0x72-0x0b
#define DATA_INDEX	0x78 //
#define DATA_LENGTH	0xdf-0x78

#define	ESC_KEY		0x1b

struct list_head queue_with_data;
struct list_head queue_without_data;


struct trans_data_list d_list[QueueLength];

char *buf_write = NULL;
char *buf_read = NULL;
char *buf_mmap = NULL;
int socket_fd;
static int getch(void)
{
	struct termios oldt,newt;
	int ch;

	if (!isatty(STDIN_FILENO)) {
		fprintf(stderr, "this problem should be run at a terminal\n");
		exit(1);
	}
	// save terminal setting
	if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
		perror("save the terminal setting");
		exit(1);
	}

	// set terminal as need
	newt = oldt;
	newt.c_lflag &= ~( ICANON | ECHO );
	if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
		perror("set terminal");
		exit(1);
	}

	ch = getchar();

	// restore termial setting
	if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
		perror("restore the termial setting");
		exit(1);
	}
	return ch;
}

static int fd = -1;
//static void close_buzzer(void);
static void open_ts(void)
{
	fd = open("/dev/zforcedebug", O_CREAT|O_RDWR|O_TRUNC, 00777);
	if (fd < 0) {
		perror("open zforcedebug device");
		exit(1);
	}
	printf("open sucess\n");
	buf_mmap = mmap(NULL,4096,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
	if(buf_mmap == MAP_FAILED)
		printf("mmap wrong................\n");
	// any function exit call will stop the buzzer
	//atexit(close_buzzer);
}


#if 0


#endif

//struct list_head * get_from_fifo(void);
//void put_to_fifo(struct list_head * list0);

void *socket_send_data(void *arg)
{

	while(1)
	{

	printf("socket send data\n");
	sleep(5);
	}

}

void *socket_receive_data(void *arg)
{
	
	int i;
	int n,len;
	struct ifreq req;     
	struct sockaddr_in *host;    
	char buff[1024];

	bzero(&req, sizeof(struct ifreq));     
	socket_fd = socket(AF_INET, SOCK_DGRAM,0);
	strcpy(req.ifr_name, "eth1");
	ioctl(socket_fd, SIOCGIFADDR, &req);
	host = (struct sockaddr_in*)&req.ifr_addr; 

	struct sockaddr_in addr_serv,addr_clie;

				
	memset(&addr_serv, 0, sizeof(addr_serv));
	addr_serv.sin_family = AF_INET;
	addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
	i = 5000;
	while(i<10000)
	{
	addr_serv.sin_port = htons(i);
	if(bind(socket_fd, (struct sockaddr *)&addr_serv, sizeof(addr_serv)) <0 )
		i++;
	else
		break;
	}

	printf("ip addr:%s,port num:%d\n",inet_ntoa(host->sin_addr),i);

	while(1)
	{
		len = sizeof(addr_clie);
		printf("server waiting for client\n");
		n = recvfrom(socket_fd, buff, 1024, 0,(struct sockaddr *) &addr_clie, (socklen_t *)&len);
		printf("client connect success!");
		//sendto(s, buff, n, 0, client, len);

	sleep(5);
	}

}
void init_queue_list(void)
{
	int i;
	char *p0;
	p0 = malloc(QueueLength*128);
	INIT_LIST_HEAD(&queue_with_data);
	INIT_LIST_HEAD(&queue_without_data);
	for(i=0;i<QueueLength;i++)
	{
		list_add_tail(&d_list[i].list1,&queue_without_data);
		d_list[i].buf = p0+i*128;
		d_list[i].count = 0;
	}

};

int main(int argc, char **argv)
{
	int key = 0;
	int i;
	int err;
	pthread_t thread_0;
	pthread_t thread_1;
	
	//pthread_mutex_t my_mutex;
	//rw_mutex
	open_ts();
	pthread_mutex_init(&rw_mutex0, NULL);
	init_queue_list();
	printf( "\nRDA Server Running.....\n" );
	// int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void*(*start_routine)(void*),  void *arg);
	err = pthread_create(&thread_0, NULL, socket_send_data, NULL);
	err = pthread_create(&thread_1, NULL, socket_receive_data, NULL);
	if(err != 0)
	{
		printf("can not create pthread ...\n");
		exit(1);
	}
	while(1)
	{	
	sleep(1);
	}
}

int push_pull_fifo(struct trans_data_list *td_list, enum transmit_flag flag0)
{

	struct list_head *list2;
	struct trans_data_list *td_list0;
	
	pthread_mutex_lock(&rw_mutex0);
	
	if(flag0 == push_flag)
	{

		if(list_empty(&queue_without_data))
		{
			printf("data overflow...\n");
			pthread_mutex_unlock(&rw_mutex0);
			return 1;
		}
		else
		{
			list2 = &queue_without_data.next;
			td_list0 = list_empty(list2,struct trans_data_list,list1);
			memcpy(td_list0->buf,td_list->buf,128);
			td_list0->count = td_list->count;
			memcpy(td_list0->addr_client,td_list->addr_client,sizeof(struct sockaddr));
			list_del_init(list2);
			list_add_tail(list2,&queue_with_data);
			return 0;
		}
	}
	else if(flag0 == pull_flag)
	{
		if(list_empty(&queue_with_data))
		{
			printf("data buf empty...\n");
			pthread_mutex_unlock(&rw_mutex0);
			return 1;
		}
		else
		{
			list2 = &queue_with_data.next;
			td_list0 = list_empty(list2,struct trans_data_list,list1);
			memcpy(td_list->buf,td_list0->buf,128);
			td_list->count = td_list0->count;
			memcpy(td_list->addr_client,td_list0->addr_client,sizeof(struct sockaddr));
			list_del_init(list2);
			list_add_tail(list2,&queue_without_data);
			return 0;
		}

	
	}
	else
	{
		return 1;
	}
	pthread_mutex_unlock(&rw_mutex0);

}

